
#include <stdio.h>

//图的边的结构体(也可以用来表示树)
struct LinkList
{
    //节点编号
    int index;
    //所有连接节点的边 包括根节点
    LinkList* next;
    // LinkList* pre;
};

void deleteLinkList(LinkList* l)
{
    LinkList* next=l;
    while (next!=NULL)
    {
        LinkList* now=next->next;
        delete next;
        next=now;
    }
}


//添加单项边
void addSinglEv(LinkList** ev,int start,int end)
{
    LinkList* l=new LinkList;
    l->index=end;

    if(ev[start]==NULL)
    {
        l->next=NULL;
        ev[start]=l;
    }
    else{
        l->next=ev[start];
        ev[start]=l;
    }
}

struct Queue
{
    int start; //队列起点
    int end;   //队列终点
    int maxLen;//队列最大元素个数
    int* data;//队列元素
};

Queue* newQueue(int maxLen)
{
    Queue* q=new Queue;
    q->maxLen=maxLen;
    q->data=new int[maxLen];
    q->start=0;
    q->end=0;
    return q;
}

void deleteQueue(Queue* q)
{
    delete q->data;
    delete q;
}

//入队
void inqueue(Queue* q,int num){
    q->data[q->end]=num;
    q->end++;
    if(q->end>=q->maxLen)
    {
        q->end=0;
    }
}

//出队
int dequeen(Queue* q){
    int num=q->data[q->start];
    q->start++;
    if(q->start>=q->maxLen)
    {
        q->start=0;
    }
    return num;
}

//队列元素多少
int sizeOfQueue(Queue* q)
{
    if(q->start==q->end)
    {
        return 0;
    }
    else{
        int len=q->end-q->start;
        if(len>0)
        {
            return len;
        }
        else{
            return len+q->maxLen;
        }
    }
}

//队列是否为空
int isEmpQueue(Queue* q)
{
    return q->start==q->end;
}


int main(){
    int n,m;
    int i,j;
    scanf("%d %d",&n,&m);
    int* result=new int[n];

    //储存节点入度
    int* input=new int[n];
    //记录树所有顶点
    LinkList** ev=new LinkList*[n];

    for(i=0;i<n;i++)
    {
        input[i]=0;
        result[i]=0;
        ev[i]=NULL;
    }

    int tmp1,tmp2;
    for(i=0;i<m;i++)
    {
        scanf("%d %d",&tmp1,&tmp2);
        tmp1--;
        tmp2--;

        //添加单向边
        addSinglEv(ev,tmp1,tmp2);
        //入度+1
        input[tmp2]++;
    }

    Queue* q=newQueue(m);
    for(i=0;i<n;i++)
    {
        if(input[i]==0)
        {
            inqueue(q,i);
            result[i]=1;
            input[i]=-1;
        }
    }

    while (!isEmpQueue(q))
    {
        int size=sizeOfQueue(q);
        for(i=0;i<size;i++)
        {   
            //删除入度为0的节点
            int index=dequeen(q);
            int value=result[index]+1;
            LinkList* l=ev[index];
            //遍历子节点
            while (l!=NULL)
            {
                int newIndex=l->index;
                //计算子节点的值
                if(result[newIndex]<value)
                {
                    result[newIndex]=value;
                }

                //子节点入度-1
                input[newIndex]--;
                //将入度为0的点入队 作为下一批的遍历对象
                if(input[newIndex]==0)
                {
                    inqueue(q,newIndex);
                    input[newIndex]=-1;
                } 
                l=l->next;
            }
        }
    }
    

    for(i=0;i<n;i++)
    {
        deleteLinkList(ev[i]);
    }
    delete ev;

    deleteQueue(q);

    for(i=0;i<n;i++)
    {
        printf("%d\n",result[i]);
    }
    delete input;
    delete result;
}